home *** CD-ROM | disk | FTP | other *** search
- ; *************************************************************************************************
- ; *
- ; * Title: ESRS.ASM
- ; * Copyright (c) January 1991, Ryu Consulting, 916/722-1939
- ; * Written by Rahner James
- ; *
- ; * This file contains the default Event Service Routine for listening and talking packets
- ; *
- ; *************************************************************************************************
-
- _ESRS_ASM_ equ 1
-
- ifdef LARGEMODEL
- .model large,c
- else
- .model small,c
- endif
-
-
- ADDRESS_S struct
- network dw ?,? ; Network number
- node dw 3 dup(?); Node address on that network
- socket dw ? ; Socket number on that node
- ADDRESS_S ends
-
-
- IPX_PACKET_S struct
- next dd ? ; Used by IPX/SPX when the ECB is active
- function dd ? ; Called after packet sent/recd, called ESR
- in_use db ? ; Set to !0 by IPX/SPX when packet is in use
- completion_code db ? ; Set by IPX/SPX after packet task is complete
- socket dw ? ; Socket to use for this ECB
- IPX_work dd ? ; Workspace used internally by IPX
- driver_work dd ?,?,? ; Workspace used internally by the IPX driver
- dest_address db 6 dup(?); Destination address for packet
- fragment_count dw ? ; Fragments descriptors that follow
- hdr dd ? ; -> IPX/SPX packet descriptor to use
- size_hdr dw ? ; Size of the IPX(30) or SPX(42) descriptor
- buffer_ptr dd ? ; -> data buffer to use for transmission/reception
- buffer_size dw ? ; Number of bytes in that buffer
-
- next_allocated dd ? ; -> next allocated packet structure
- next_sibling dd ? ; -> next packet for stream and condition
- parent dd ? ; -> parent stream definition packet
- default_buffer dd ? ; -> default buffer to use for IPX or SPX
- default_size dw ? ; Size of the default buffer
- done_flag dd ? ; Set by the ESR with the completion code
-
- checksum dw ? ; Dummy checksum of the 30-byte packet header
- packet_length dw ? ; Length of the complete IPX packet, filled by IPX/SPX
- control db ? ; Transport control byte for internetwork bridges
- packet_type db ? ; Packet type: IPX(4)/SPX(5), defined by Xerox
-
- dest_network dd ? ; Destination network address
- dest_node db 6 dup(?); Destination node address
- dest_socket dw ? ; Destination socket
-
- src_network dd ? ; Source network address
- src_node db 6 dup(?); Source node address
- src_socket dw ? ; Source socket
- IPX_PACKET_S ends
-
-
- XPX_STREAM_S struct
- next dd ? ; -> next stream structure that has been opened
- first_allocated dd ? ; -> first allocated packet for this handle
- last_allocated dd ? ; -> last allocated packet for this handle
- first_unread dd ? ; -> first unread packet
- last_unread dd ? ; -> last unread packet in the list
- first_free dd ? ; -> first packet available for talking
- first_error dd ? ; -> first packet that encountered an error
- last_error dd ? ; -> last packet that encountered an error
-
- dest_network dd ? ; Destination network address
- dest_node db 6 dup(?); Destination node address
- dest_socket dw ? ; Destination socket
- local_target db 6 dup(?); Node address of the local target for the destination
- connection_ID dw ? ; Connection ID used for SPX
- total_talkers dw ? ; Number of talkers allocated to this stream
- total_listeners dw ? ; Number of listeners allocated to this stream
- unread_count dw ? ; Number of packets unread by application
- free_count dw ? ; Number of packets ready for talking
- maximum_unread dw ? ; Maximum number of unread packets that have occurred so far
- error_count dw ? ; Number of unprocessed error packets
-
- total_transmissions dd ? ; Number of transmissions performed by this stream
- total_receptions dd ? ; Number of receptions performed by this stream
- total_errors dd ? ; Number of errors encountered by this stream
- XPX_STREAM_S ends
-
- .data
- extern _Ignore_Nomatch:byte, _Our_Address:word, IPX_Vector:dword, _First_Stream:dword
- extern _First_Nomatch:dword, _Last_Nomatch:dword, _Total_Nomatchs:word
-
- .code
-
- Last_Broad_Ptr dw 0,0 ; -> last checked broadcast stream, must be in code segment
-
-
- ; *************************************************************************************************
- ; *
- ; * void far TALK_ESR( void )
- ; * Event Service Routine (ESR) for IPX functions and their talking packets
- ; *
- ; * Given:
- ; * AL = 0 if AES called this ESR, 0xff if this is a normal event (only possibility)
- ; * ES:SI -> ECB that just finished talking
- ; *
- ; * Returns:
- ; * Packet either glued onto the free list or the error list
- ; *
- ; * Note:
- ; * Interrupts are enabled at this point and should stay that way
- ; *
- ; *************************************************************************************************
- talk_esr proc far
-
- ; *
- ; * See if we need to set the done flag
- ; *
- lds bx, es:[si].IPX_PACKET_S.done_flag ; DS:BX -> process done flag
- mov cl, es:[si].IPX_PACKET_S.completion_code
- mov ax, ds
- or ax, bx
- jz @F ; If DS:BX -> NULL, just skip it
- mov [bx], cl ; Set the flag with our completion code
- mov word ptr es:[si].IPX_PACKET_S.done_flag, 0 ; Make it NULL for the next guy
- mov word ptr es:[si].IPX_PACKET_S.done_flag+2, 0
-
- ; *
- ; * Check whether the packet goes in the error list or the free list
- ; *
- @@: lds bx, es:[si].IPX_PACKET_S.parent ; DS:BX -> parent structure
- or cl, cl ; See if we got a transmission error
- jnz talk20_esr ; Jump if we got one
-
- ; *
- ; * Here's where we process the good transmissions
- ; *
- add word ptr [bx].XPX_STREAM_S.total_transmissions, 1
- adc word ptr [bx].XPX_STREAM_S.total_transmissions+2, 0
- inc [bx].XPX_STREAM_S.free_count;
-
- mov cx, word ptr [bx].XPX_STREAM_S.first_free ; DX:CX -> first free
- mov dx, word ptr [bx].XPX_STREAM_S.first_free+2
- mov word ptr [bx].XPX_STREAM_S.first_free, si ; Set us as the new first
- mov word ptr [bx].XPX_STREAM_S.first_free+2, es
- mov word ptr es:[si].IPX_PACKET_S.next_sibling, cx ; Place us with our brothers and sisters
- mov word ptr es:[si].IPX_PACKET_S.next_sibling+2, dx
-
- talk10_esr:
- ret
-
- ; *
- ; * Here's where we take care of our challenged packets
- ; *
- talk20_esr:
- add word ptr [bx].XPX_STREAM_S.total_errors, 1
- adc word ptr [bx].XPX_STREAM_S.total_errors+2, 0
- inc [bx].XPX_STREAM_S.error_count
-
- mov cx, word ptr [bx].XPX_STREAM_S.last_error ; DX:CX -> last error packet
- mov dx, word ptr [bx].XPX_STREAM_S.last_error+2
- mov word ptr [bx].XPX_STREAM_S.last_error, si ; Set us as the new last error
- mov word ptr [bx].XPX_STREAM_S.last_error+2, es
- mov word ptr es:[si].IPX_PACKET_S.next_sibling, 0 ; Place us with our brothers and sisters
- mov word ptr es:[si].IPX_PACKET_S.next_sibling+2, 0
-
- mov ax, cx ; See if we need to do the first as well
- or ax, dx
- jnz @F
-
- mov word ptr [bx].XPX_STREAM_S.first_error, si ; Set us as the new first error
- mov word ptr [bx].XPX_STREAM_S.first_error+2, es
- ret
-
- @@: mov ds, dx ; DS:BX -> the first born
- mov bx, cx
- mov word ptr [bx].IPX_PACKET_S.next_sibling, si ; Point the old end at us
- mov word ptr [bx].IPX_PACKET_S.next_sibling+2, es
- ret
-
- talk_esr endp
-
-
- ; *************************************************************************************************
- ; *
- ; * void far LISTEN_ESR( void )
- ; * Event Service Routine (ESR) for IPX functions and their listening packets
- ; *
- ; * Given:
- ; * AL = 0 if AES called this ESR, 0xff if this is a normal event (only possibility)
- ; * ES:SI -> ECB that just got something
- ; *
- ; * Returns:
- ; * Packet put at the end of the unread packet list of the stream it was intended for
- ; *
- ; * Note:
- ; * Interrupts are enabled at this point and should stay that way
- ; * This packet may not be put with its parent if there are multiple parents
- ; * associated with one socket
- ; *
- ; *************************************************************************************************
- listen_esr proc far
-
- mov ax, @Data ; DS = our data segment
- mov ds, ax
- ; *
- ; * First see if we sent it as a broadcast and it got back to us
- ; *
- mov ax, _Our_Address.ADDRESS_S.node+4 ; Do it this way to eliminate the setup
- cmp word ptr es:[si].IPX_PACKET_S.src_node+4, ax ; for a CMPSW and the LSBSMW (Least
- jne listen10_esr ; Significant B.S. Motorola Word) has the
- mov ax, _Our_Address.ADDRESS_S.node+2 ; greatest chance of being different and
- cmp word ptr es:[si].IPX_PACKET_S.src_node+2, ax ; this condition should happen rarely
- jne listen10_esr
- mov ax, _Our_Address.ADDRESS_S.node
- cmp word ptr es:[si].IPX_PACKET_S.src_node, ax
- jne listen10_esr
- mov ax, _Our_Address.ADDRESS_S.network+2
- cmp word ptr es:[si].IPX_PACKET_S.src_network+2, ax
- jne listen10_esr
- mov ax, _Our_Address.ADDRESS_S.network
- cmp word ptr es:[si].IPX_PACKET_S.src_network, ax
- jne listen10_esr
-
- listen_again_buckwheat:
- mov bx, 4 ; BX = IPX Listen For Packet command
- call dword ptr IPX_Vector ; Call the IPX function
- ret
-
- ; *
- ; * See if we need to set the done flag
- ; *
- listen10_esr:
- mov ax, es:[si].IPX_PACKET_S.packet_length ; Change this into a more rational format
- xchg ah, al
- sub ax, es:[si].IPX_PACKET_S.size_hdr
- mov es:[si].IPX_PACKET_S.packet_length, ax
-
- lds bx, es:[si].IPX_PACKET_S.done_flag ; DS:BX -> process done flag
- mov cl, es:[si].IPX_PACKET_S.completion_code
- mov ax, ds
- or ax, bx
- jz listen20_esr ; If DS:BX -> NULL, just skip it
- mov [bx], cl ; Set the flag with our completion code
- mov word ptr es:[si].IPX_PACKET_S.done_flag, 0 ; Make it NULL for the next guy
- mov word ptr es:[si].IPX_PACKET_S.done_flag+2, 0
-
- ; *
- ; * Check whether the packet goes in the error list or the free list
- ; *
- listen20_esr:
- lds bx, es:[si].IPX_PACKET_S.parent ; DS:BX -> parent structure
- or cl, cl ; See if we got a reception error
- jz listen40_esr ; Jump if we have an unimpaired reception
-
- ; *
- ; * Here's where we take care of our datistically challenged packets
- ; *
- add word ptr [bx].XPX_STREAM_S.total_errors, 1
- adc word ptr [bx].XPX_STREAM_S.total_errors+2, 0
- inc [bx].XPX_STREAM_S.error_count
-
- mov cx, word ptr [bx].XPX_STREAM_S.last_error ; DX:CX -> last error packet
- mov dx, word ptr [bx].XPX_STREAM_S.last_error+2
- mov word ptr [bx].XPX_STREAM_S.last_error, si ; Set us as the new last error
- mov word ptr [bx].XPX_STREAM_S.last_error+2, es
- mov word ptr es:[si].IPX_PACKET_S.next_sibling, 0 ; Place us with our brothers and sisters
- mov word ptr es:[si].IPX_PACKET_S.next_sibling+2, 0
-
- mov ax, dx ; See if we are the only packet here
- or ax, cx
- jnz @F ; Skip out of this ESR if we are not alone
-
- mov word ptr [bx].XPX_STREAM_S.first_error, si ; Set us as the new first error
- mov word ptr [bx].XPX_STREAM_S.first_error+2, es
- ret
-
- @@: mov ds, dx ; DS:BX -> the first born
- mov bx, cx
- mov word ptr [bx].IPX_PACKET_S.next_sibling, si ; Point the old end at us
- mov word ptr [bx].IPX_PACKET_S.next_sibling+2, es
- ret
-
- ; *
- ; * Here's where we process the good transmissions
- ; *
- listen40_esr:
- push ds ; DX:CX -> the first stream structure
- mov ax, @Data
- mov ds, ax
- mov cx, word ptr _First_Stream
- mov dx, word ptr _First_Stream+2
- pop ds
- mov Last_Broad_Ptr, 0
- mov Last_Broad_Ptr+2, 0
-
- listen50_esr:
- cmp [bx].XPX_STREAM_S.total_listeners, 0 ; See if it's a READ ONLY stream
- jz not_parent ; Skip this one if it is READ ONLY
-
- mov ax, word ptr [bx].XPX_STREAM_S.dest_node ; See if our parent will take anything (all 0xFF's)
- and ax, word ptr [bx].XPX_STREAM_S.dest_node+2
- and ax, word ptr [bx].XPX_STREAM_S.dest_node+4
- inc ax
- jnz @F ; Skip if it is not a broadcast type
- mov Last_Broad_Ptr, bx ; Save this for later
- mov Last_Broad_Ptr+2, ds
- jmp short not_parent ; Still not necessarily the right one
-
- @@: mov ax, word ptr [bx].XPX_STREAM_S.local_target+4 ; Match the parent destination up first
- cmp word ptr es:[si].IPX_PACKET_S.src_node+4, ax
- jne not_parent ; Skip if this is not my mommy
- mov ax, word ptr [bx].XPX_STREAM_S.local_target+2
- cmp word ptr es:[si].IPX_PACKET_S.src_node+2, ax
- jne not_parent
- mov ax, word ptr [bx].XPX_STREAM_S.local_target
- cmp word ptr es:[si].IPX_PACKET_S.src_node, ax
- jne not_parent
-
- mov ax, word ptr es:[si].IPX_PACKET_S.src_network+2
- cmp word ptr es:[si].IPX_PACKET_S.dest_network+2, ax
- jne not_parent
- mov ax, word ptr es:[si].IPX_PACKET_S.src_network
- cmp word ptr es:[si].IPX_PACKET_S.dest_network, ax
- je found_listener
-
- ; *
- ; * At this point, the current structure has been determined not to be suitable
- ; *
- not_parent:
- mov ax, cx ; See if we are at the end of our rope
- or ax, dx
- jz no_listener ; No stream match found
-
- mov ds, dx ; DS:BX -> next stream definition
- mov bx, cx
- mov cx, word ptr [bx].XPX_STREAM_S.next ; DX:CX -> next stream packet after this one
- mov dx, word ptr [bx].XPX_STREAM_S.next+2
- jmp listen50_esr ; Loop until we poop
-
- ; *
- ; * Stream ID matches up with the destination address, so we add this packet to that stream list
- ; *
- found_listener:
- add word ptr [bx].XPX_STREAM_S.total_receptions, 1
- adc word ptr [bx].XPX_STREAM_S.total_receptions+2, 0
- inc [bx].XPX_STREAM_S.unread_count
- mov ax, [bx].XPX_STREAM_S.unread_count ; Update our statistics
- cmp [bx].XPX_STREAM_S.maximum_unread, ax
- jnc found10_listener ; Skip if no need to update
- mov [bx].XPX_STREAM_S.maximum_unread, ax
- found10_listener:
- mov cx, word ptr [bx].XPX_STREAM_S.last_unread ; DX:CX -> last unread packet
- mov dx, word ptr [bx].XPX_STREAM_S.last_unread+2
- mov word ptr [bx].XPX_STREAM_S.last_unread, si ; Set us as the new last unread packet
- mov word ptr [bx].XPX_STREAM_S.last_unread+2, es
- mov word ptr es:[si].IPX_PACKET_S.next_sibling, 0 ; Place us with our new brothers and sisters
- mov word ptr es:[si].IPX_PACKET_S.next_sibling+2, 0
-
- mov ax, cx ; See if we need to do the first as well
- or ax, dx
- jnz @F ; All done if there are others
-
- mov word ptr [bx].XPX_STREAM_S.first_unread, si ; Set us as the new first unread as well
- mov word ptr [bx].XPX_STREAM_S.first_unread+2, es
- ret
-
- @@: mov ds, dx ; DS:BX -> the first born
- mov bx, cx
- mov word ptr [bx].IPX_PACKET_S.next_sibling, si ; Point the old end at us
- mov word ptr [bx].IPX_PACKET_S.next_sibling+2, es
- ret
-
- ; *
- ; * At this point, the packet is an orphan and must be sent off to farm or be glue
- ; *
- no_listener:
- lds bx, dword ptr Last_Broad_Ptr ; DS:BX -> last found broadcast stream
- mov ax, ds
- or ax, bx
- jnz found_listener ; If one was found, use that in the last resort
-
- cmp _Ignore_Nomatch, al ; See if we just ignore the orphans or adopt them, (AL==0 here)
- jz no10_listener ; Skip to adopt
- jmp listen_again_buckwheat ; Put back on the mountaintop
-
- no10_listener:
- mov ax, @Data ; DS = our most lovable data segment
- mov ds, ax
-
- inc _Total_Nomatchs
- mov cx, word ptr _Last_Nomatch ; DX:CX -> last error packet
- mov dx, word ptr _Last_Nomatch+2
- mov word ptr _Last_Nomatch, si ; Make it point to us
- mov word ptr _Last_Nomatch+2, es
- mov word ptr es:[si].IPX_PACKET_S.next_sibling, 0 ; Place us with our new brothers and sisters
- mov word ptr es:[si].IPX_PACKET_S.next_sibling+2, 0
-
- mov ax, cx ; See if we need to do the first as well
- or ax, dx
- jnz @F ; All done if there are others
-
- mov word ptr _First_Nomatch, si ; Set us as the new first error
- mov word ptr _First_Nomatch+2, es
- ret
-
- @@: mov ds, dx ; DS:BX -> the first born
- mov bx, cx
- mov word ptr [bx].IPX_PACKET_S.next_sibling, si ; Point the old end at us
- mov word ptr [bx].IPX_PACKET_S.next_sibling+2, es
- ret
-
- listen_esr endp
-
-
- end
-
-
-